﻿using StarMathLib;

namespace GearSynth
{
    internal class userDefinedGoals
    {
        /* The best-first search employed here requires us to order our list (e.g. tree)
         * by a single value. Hence we need to combine objectives into a single objective.
         * This is done below on line 54 of GearSynthMainSearchProcess, where f0 is mass
         * and f1 is inefficiency. */
        internal double w { get; private set; }
        /// <summary>
        /// Gets or sets the input location.
        /// </summary>
        /// <value>The input location.</value>
        internal double[,] inputLocation { get; private set; }

        /// <summary>
        /// Gets or sets the output location.
        /// </summary>
        /// <value>The output location.</value>
        internal double[,] outputLocation { get; private set; }

        /// <summary>
        /// Gets or sets the tolerance speed of acheiving the actual
        /// output speed. This is really a fractional, dimensionless error. 
        /// </summary>
        /// <value>The speed tolerance.</value>
        internal double SpeedTolerance { get; private set; }
        /// <summary>
        /// Gets or sets the tolerance of acheiving the output location.
        /// This is used by the output location constraint to determine
        /// when a solution is truly feasible. This has unit of inch or mm.
        /// </summary>
        /// <value>The location tolerance.</value>
        internal double LocationTolerance { get; private set; }
        /// <summary>
        /// Gets or sets the wear (surface fatique) safety factor).
        /// </summary>
        /// <value>The NFC.</value>
        internal double Nfc { get; private set; }
        /// <summary>
        /// Gets or sets the bending fatigue safety factor.
        /// </summary>
        /// <value>The NFB.</value>
        internal double Nfb { get; private set; }
        /// <summary>
        /// Gets or sets the input speed.
        /// </summary>
        /// <value>The input speed.</value>
        internal double inputSpeed { get; private set; }
        /// <summary>
        /// Gets or sets the output speed.
        /// </summary>
        /// <value>The output speed.</value>
        internal double outputSpeed { get; private set; }
        /// <summary>
        /// Gets or sets the input direction.
        /// </summary>
        /// <value>The input direction.</value>
        internal Spin inputDirection { get; private set; }
        /// <summary>
        /// Gets or sets the output direction.
        /// </summary>
        /// <value>The output direction.</value>
        internal Spin outputDirection { get; private set; }
        /// <summary>
        /// Gets or sets the input torque.
        /// </summary>
        /// <value>The input torque.</value>
        internal double inputTorque { get; private set; } //ft lbs
        /// <summary>
        /// Gets or sets the output torque.
        /// </summary>
        /// <value>The output torque.</value>
        internal double outputTorque { get; private set; }
        /// <summary>
        /// Gets or sets the max X.
        /// </summary>
        /// <value>The max X.</value>
        internal double maxX { get; private set; }
        /// <summary>
        /// Gets or sets the min X.
        /// </summary>
        /// <value>The min X.</value>
        internal double minX { get; private set; }
        /// <summary>
        /// Gets or sets the max Y.
        /// </summary>
        /// <value>The max Y.</value>
        internal double maxY { get; private set; }
        /// <summary>
        /// Gets or sets the min Y.
        /// </summary>
        /// <value>The min Y.</value>
        internal double minY { get; private set; }
        /// <summary>
        /// Gets or sets the max Z.
        /// </summary>
        /// <value>The max Z.</value>
        internal double maxZ { get; private set; }
        /// <summary>
        /// Gets or sets the min Z.
        /// </summary>
        /// <value>The min Z.</value>
        internal double minZ { get; private set; }

        internal userDefinedGoals()
        {
            inputLocation = new double[4, 4];
            outputLocation = new double[4, 4];
        }


        internal static userDefinedGoals GetGoals()
        {
            /* this function could/should inroduce a window and series of GUI elements to
             * retireve the description of the problem from the user. In lieu of that, we
             * simply define them here. */
            var goals = new userDefinedGoals
                            {
                                w = 0.01,
                                inputLocation = StarMath.makeIdentity(4),
                                LocationTolerance = 0.5, //inches
                                inputSpeed = 300,
                                inputDirection = Spin.Clockwise,
                                outputSpeed = 950,
                                outputDirection = Spin.Unspecified,
                                SpeedTolerance = 0.05,
                                Nfb = 2,
                                Nfc = 2,
                                inputTorque = 1.0, //ft lbs
                                outputTorque = 0,
                                maxX = 10,
                                minX = -10,
                                maxY = 10,
                                minY = -10,
                                maxZ = 10,
                                minZ = -10
                            };
            goals.outputLocation = StarMath.multiply(goals.inputLocation, StarMath.Translate(4.0, 2.0, 3.0));
            goals.outputLocation = StarMath.multiply(goals.outputLocation, StarMath.RotationY(-30));
            return goals;
        }
    }
}